#!/usr/bin/env ruby

require File.dirname(__FILE__) + '/../test_helper'

require 'test/unit'
require 'container/mongrel_controller'


class MongrelInstanceTest < Test::Unit::TestCase

  def setup
    @sandbox = Sandbox.new
    @controller = MongrelController.new(@sandbox.root)
    # do not _really_ execute any shell commands
    @controller.stubs(:execute)
    @controller.stubs(:chown)
  end

  def teardown
    @sandbox.clean_up
  end
  
  def test_find_all
    setup_test_container

    assert_equal 'mongrel(foo:4000)', MongrelInstance.find_all(@controller, :host => 'foo', :port => 4000).join(', ')
    assert_equal 'mongrel(bar:4002)', MongrelInstance.find_all(@controller, :host => 'bar', :port => 4002).join(', ')
    assert_equal 'mongrel(bar:4001.reserve)', MongrelInstance.find_all(@controller, :host => 'bar', :port => 4001).join(', ')
    
    assert_equal 'mongrel(foo:4000), mongrel(foo:4001), mongrel(foo:4002.reserve)',
                 MongrelInstance.find_all(@controller, :host => 'foo').join(', ')

    assert_equal 'mongrel(bar:4000), mongrel(bar:4001.reserve), mongrel(bar:4002), ' +
                 'mongrel(foo:4000), mongrel(foo:4001), mongrel(foo:4002.reserve)',
                 MongrelInstance.find_all(@controller).join(', ')

    assert_raises(RuntimeError) { MongrelInstance.find_active(@controller, :host => 'unknown') }
  end

  def test_find_active
    setup_test_container
    
    assert_equal 'mongrel(foo:4000)', MongrelInstance.find_active(@controller, :host => 'foo', :port => 4000).join(', ')
    assert_equal 'mongrel(bar:4002)', MongrelInstance.find_active(@controller, :host => 'bar', :port => 4002).join(', ')

    assert_equal 'mongrel(foo:4000), mongrel(foo:4001)',
                 MongrelInstance.find_active(@controller, :host => 'foo').join(', ')

    assert_equal 'mongrel(bar:4000), mongrel(bar:4002), mongrel(foo:4000), mongrel(foo:4001)',
                 MongrelInstance.find_active(@controller).join(', ')

    assert_raises(RuntimeError) { MongrelInstance.find_active(@controller, :host => 'foo', :port => 4002) }
    assert_raises(RuntimeError) { MongrelInstance.find_active(@controller, :host => 'bar', :port => 4001) }
    assert_raises(RuntimeError) { MongrelInstance.find_active(@controller, :host => 'unknown') }
  end

  def test_find_active_should_cope_with_ip_addresses
    @controller.create_container(['127.0.0.1', '127.0.0.2'], 4000)

    assert_equal 'mongrel(127.0.0.1:4000), mongrel(127.0.0.2:4000)',
                 MongrelInstance.find_active(@controller).join(', ')
  end

  def test_parse_config_path
    assert_parse_result ['container/root', 'myhost', '12345', false],
                        'container/root/config/mongrel.myhost.12345.config'
    assert_parse_result ['.', 'myhost', '12345', true], 
                        './config/mongrel.myhost.12345.config.reserve'
    assert_raises(RuntimeError) { MongrelInstance.parse_config_path('./config/foo') }
    assert_raises(RuntimeError) { MongrelInstance.parse_config_path('./foo/mongrel.myhost.12345.config') }
  end

  def assert_parse_result(expected_parameters, config_path)
    expected_container_root, expected_host, expected_port, expected_reserve = expected_parameters

    result = MongrelInstance.parse_config_path(config_path)

    assert_equal expected_container_root, result[:container_root], "Container root is not as expected in #{result.inspect}"
    assert_equal expected_host, result[:host], "Host is not as expected in #{result.inspect}"
    assert_equal expected_port, result[:port], "Port is not as expected in #{result.inspect}"
    assert_equal expected_reserve, result[:reserve], "Reserve flag is not as expected in #{result.inspect}"
  end


  def setup_test_container
    @controller.create_container(['foo', 'bar'], [4000, 4001, 4002])

    cd File.join(@sandbox.root, 'config') do
      mv 'monit.foo.4001.config.reserve', 'monit.foo.4001.config'
      mv 'monit.bar.4002.config.reserve', 'monit.bar.4002.config'
    end
  end

end